package org.lqk.pool.socket2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * SocketConnection的代理工厂类
 * 
 * connection调用方法，都会导致从线程池的取出与回收，这种方式在socket里面是不合适的
 * 
 * 这个类的作用只是说明一下，借助spring，我们可以做更多的封装。
 * 
 * @author bert
 *
 */

public class SocketConnectionProxyFactory implements FactoryBean, InitializingBean {
	private Object proxyObject;
	private Class objectClass;
	private GenericObjectPool<SocketConnection> objectPool;
	private PooledObjectFactory<SocketConnection> pooledObjectFactory;
	private SocketConnectionConfig socketConnectionConfig;

	@Override
	public Object getObject() throws Exception {
		return  proxyObject;
	}

	@Override
	public Class<SocketConnection> getObjectType() {
		return objectClass;
	}

	@Override
	public boolean isSingleton() {
		return true;  
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		pooledObjectFactory = new PooledSocketConnectionFactory(socketConnectionConfig);
		objectPool = new GenericObjectPool<SocketConnection>(pooledObjectFactory);
		// 这样做的话，每次connection调用方法，都会导致从线程池的取出与回收
		proxyObject = Proxy.newProxyInstance(classLoader, new Class[] { objectClass }, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				SocketConnection connection = objectPool.borrowObject();
				try {
					return method.invoke(connection, args);
				} catch (Exception e) {
					throw e;
				} finally {
					objectPool.returnObject(connection);
				}
			}

		});
	}


}
